export function patch(oldVnode, vnode) {
  // 递归创建真实节点
  // 判断是跟新还是 要渲染
  //
  if(!oldVnode) {
    // 这个是组件的挂载
    return createElm(vnode)
  }else{
    const isRealElement = oldVnode.nodeType
    if(isRealElement) {
      const oldEle = oldVnode
      const parentElm = oldEle.parentNode
      let el = createElm(vnode)
      parentElm.insertBefore(el, oldEle.nextSibling)
      parentElm.removeChild(oldEle);
      return el;
    }else{
      // 这个是两个 虚拟dom比较了
      // diff算法  
      // 平级比较  标签类型或者key不一样直接不比了
      // 
      if(oldVnode.tag !== vnode.tag) {
        oldVnode.el.parentNode.replaceChild(createElm(vnode) ,oldVnode.el)
      }

      // 文本的情况
      if(!oldVnode.tag) {
        if(oldVnode.text !== vnode.text) {
          oldVnode.el.textContent = vnode.text
        }
        return
      }

      // 标签一样 
      console.log('patchvnode', vnode, oldVnode)
      let el = vnode.el = oldVnode.el
      updateProperties(vnode, oldVnode.data)

      // 需要比对儿子
      let oldChildren = oldVnode.children || []
      let newChildren = vnode.children || []
      if(oldChildren.length > 0 && newChildren.length > 0) {
        // ..
        updateChildren(el, oldChildren, newChildren);

      }else if(newChildren.length > 0){
        for(let i = 0; i<newChildren.length;i++) {
          let child = newChildren[i]
          el.appendChild(createElm(child))
        }
      }else if(oldChildren.length > 0){
        el.innerHTML = ''
      }
    }
  }

  
}

function isSameVnode(oldVnode, newVnode) {
  return (oldVnode.tag == newVnode.tag) && (oldVnode.key === newVnode.key)
}

// 双指针 比对
function updateChildren(parent, oldChildren, newChildren) {

  let oldStartIndex = 0
  let oldStartVnode = oldChildren[0]
  let oldEndIndex = oldChildren.length -1
  let oldEndVnode = oldChildren[oldEndIndex]
  
  let newStartIndex = 0
  let newStartVnode = newChildren[0]
  let newEndIndex = newChildren.length -1
  let newEndVnode = newChildren[newEndIndex]

  const makeIndexByKey = (children) => {
    let map = {}
    children.forEach((item, index) => {
      if(item.key) {
        map[item.key] = index
      }
    })
    return map
  }
  let map = makeIndexByKey(oldChildren)

  // debugger
  while(oldStartIndex <= oldEndIndex && newStartIndex <= newEndIndex) {
    // 如果 oldStartVnode 没有的话  就在向前一位   针对指针在移动的过程中  因为元素被移走了 会有undefined的情况
    if(!oldStartVnode) {
      oldStartVnode = oldChildren[++oldStartIndex]
    }else if(!oldEndVnode) {
      oldEndVnode = oldChildren[--oldEndIndex]
    }
    // 优化向后插入  头和头
    if(isSameVnode(oldStartVnode, newStartVnode)) {
      // 就需要比较属性  
      patch(oldStartVnode, newStartVnode)
      oldStartVnode = oldChildren[++oldStartIndex]
      newStartVnode = newChildren[++newStartIndex]
    // 优化向前插入  尾和尾
    }else if(isSameVnode(oldEndVnode, newEndVnode)) {
      patch(oldEndVnode, newEndVnode)
      oldEndVnode = oldChildren[--oldEndIndex]
      newEndVnode = newChildren[--newEndIndex]
      // 头移尾  头和尾
    }else if(isSameVnode(oldStartVnode, newEndVnode)) {
      patch(oldStartVnode, newEndVnode)
      parent.insertBefore(oldStartVnode.el, oldEndVnode.el.nextSibling)
      oldStartVnode = oldChildren[++oldStartIndex]
      newEndVnode = newChildren[--newEndIndex]
      // 尾和头
    }else if(isSameVnode(oldEndVnode, newStartVnode)) {
      patch(oldEndVnode, newStartVnode)
      parent.insertBefore(oldEndVnode.el, oldStartVnode.el)
      oldEndVnode = oldChildren[--oldEndIndex]
      newStartVnode = newChildren[++newStartIndex]
    }else{
      // 暴力对比   乱序
      // 拿新的虚拟节点去映射表中查找有没有  如果有找到则移动到 oldStartIndex 前面  没有的话就插入到oldStartIndex 前面
      let moveIndex = map[newStartVnode.key]
      // 找不到
      if(!moveIndex) {
        parent.insertBefore(createElm(newStartVnode), oldStartVnode.el)
      }else{
        // 找到了
        let moveVnode = oldChildren[moveIndex]
        oldChildren[moveIndex] = undefined
        parent.insertBefore(moveVnode.el, oldStartVnode.el)
        patch(moveVnode, newStartVnode)
      }
      newStartVnode = newChildren[++newStartIndex]
    }
  }

  if(newStartIndex <= newEndIndex) {
    for(let i = newStartIndex; i<=newEndIndex; i++) {
      let flag = newChildren[newEndIndex+1] ? newChildren[newEndIndex + 1].el : null
      parent.insertBefore(createElm(newChildren[i]), flag)
      // newChildren[newEndIndex+1] = null
      // parent.appendChild(createElm(newChildren[i]))
    }
  }
  // 删除多余的元素
  if(oldStartVnode <= oldEndIndex) {
    for(let i=oldStartIndex; i<=oldEndIndex;i++) {
      let child = oldChildren[i]
      if(child) {
        parent.removeChild(child.el)
      }
    }
  }

}



function createComponent(vnode) {
  let i = vnode.data
  if((i=i.hook) && (i = i.init)){
    i(vnode)
  } 
  if(vnode.componentInstance) {
    return true
  }
}

export function createElm(vnode) {
  let {tag, children, key, data, text} = vnode
  // console.log(vnode, '总的vnode')
  if(typeof tag === 'string') {
    // 有可能是组件
    if(createComponent(vnode)) {
      return vnode.componentInstance.$el 
    }
    vnode.el = document.createElement(tag)
    updateProperties(vnode);
    children.forEach(child => {
      return vnode.el.appendChild(createElm(child))
    })
  }else{
    vnode.el = document.createTextNode(text)
  }
  return vnode.el
}
// 更新属性
function updateProperties(vnode, oldProps = {}) {
  let newProps = vnode.data || {}

  let el = vnode.el

  // 老的有 新的没有  那就删除
  let newStyle = newProps.style || {}
  let oldStyle = oldProps.style || {}
  for(let key in oldStyle) {
    if(!newStyle[key]) {
      el.style[key] = '';
    }
  }

  for(let key in newProps) {
    if(!newProps[key]) {
      el.removeAttribute(key)
    }
  }


  for(let key in newProps) {
    if(key === 'style') {
      for(let styleName in newProps.style) {
        el.style[styleName] = newProps.style[styleName]
      }
    }else if(key === 'class') {
      el.className = newProps.class
    }else{
      el.setAttribute(key, newProps[key])
    }
  }
}